/*
 * NormalFitness.java
 *
 * Created on den 30 mars 2007, 23:30
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package grex.fitnessfunctions;

import grex.EvolutionListener;
import grex.EvolutionProcess;
import grex.GP;
import grex.Options;
import grex.Prediction;
import grex.PredictionContainer;
import grex.genes.GeneException;

import java.io.Serializable;
import java.util.ArrayList;

/**
 *
 * @author rik
 */
public class TombolaFitness implements IFitnessFunction, Serializable, EvolutionListener{
    ArrayList<PredictionContainer> tombola;
    final int TOMBOLA_SIZE=3;
    final int TOMBOLA_GENERATIONS=3;
    /** Creates a new instance of NormalFitness */
    public TombolaFitness() {
    }

    public double calcFitness(GP gp) throws GeneException {
        Options options = gp.getOptions();
                gp.train();

        double trainFitness = 0;

        for (PredictionContainer slot : tombola) {
            double tmpFitness = 0;
            gp.execute(slot);
            for (Prediction p : slot.values()) {
                if (p.getPrediction() == p.getTargetValue()) {
                    tmpFitness++;
                }                
            }
            trainFitness = Math.max(trainFitness, 1.0 - tmpFitness / slot.size());
        }

        trainFitness = 100*trainFitness;
        return trainFitness + gp.getNrOfNodes()*options.getPUNISHMENT_FOR_LENGTH();

    }

    private void initTombola(double[][] trainData){

            tombola=new ArrayList<PredictionContainer>(TOMBOLA_SIZE);
            for(int i = 0; i < TOMBOLA_SIZE;i++){
                tombola.add(new PredictionContainer(trainData.length/(TOMBOLA_SIZE-1)));
            }
            for(double[] p:trainData){
                tombola.get(Options.rnd.nextInt(TOMBOLA_SIZE)).put(p,new Prediction(p));
            }
    }

    public void evolutionStarted(EvolutionProcess source) {
        double[][] trainData = source.getData().getTrainFold(source.getOptions().getTestFOLD());
        initTombola(trainData);
    }

    public void generationTerminated(EvolutionProcess source) {
        if(source.getCurrentGeneration()%TOMBOLA_GENERATIONS==0){
            double[][] trainData = source.getData().getTrainFold(source.getOptions().getTestFOLD());
            initTombola(trainData);
            source.getWorld().getPopulation().notifyGPofDataChange();
        }
    }

    public void batchTerminated(EvolutionProcess source) {
    }

    public void evolutionTerminated(EvolutionProcess source) {
    }

    public void evolutionProcessTerminated(EvolutionProcess source) {
    }

}
